package com.dlc.shop.delivery.common.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaOrderShippingService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaOrderShippingServiceImpl;
import cn.binarywang.wx.miniapp.bean.shop.request.shipping.*;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dlc.shop.bean.app.dto.DeliveryDto;
import com.dlc.shop.bean.app.dto.DeliveryInfoDto;
import com.dlc.shop.bean.enums.*;
import com.dlc.shop.bean.event.FlowSystemTypeEnum;
import com.dlc.shop.bean.model.*;
import com.dlc.shop.common.enums.PayType;
import com.dlc.shop.common.enums.StatusEnum;
import com.dlc.shop.common.exception.YamiShopBindException;
import com.dlc.shop.config.WxConfig;
import com.dlc.shop.dao.OrderItemMapper;
import com.dlc.shop.delivery.common.dao.DeliveryOrderMapper;
import com.dlc.shop.delivery.common.manager.DeliveryPrintManager;
import com.dlc.shop.delivery.common.model.DeliveryOrder;
import com.dlc.shop.delivery.common.model.DeliveryOrderItem;
import com.dlc.shop.delivery.common.param.DeliveryOrderItemParam;
import com.dlc.shop.delivery.common.param.OrderItemParam;
import com.dlc.shop.delivery.common.service.DeliveryOrderItemService;
import com.dlc.shop.delivery.common.service.DeliveryOrderService;
import com.dlc.shop.service.*;
import lombok.AllArgsConstructor;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 *
 *
 * @author lhd
 * @date 2020-04-22 15:46:05
 */
@Service
@AllArgsConstructor
public class DeliveryOrderServiceImpl extends ServiceImpl<DeliveryOrderMapper, DeliveryOrder> implements DeliveryOrderService {

    private final DeliveryOrderMapper deliveryOrderMapper;
    private final DeliveryOrderItemService deliveryOrderItemService;
    private final OrderService orderService;
    private final NotifyTemplateService notifyTemplateService;
    private final DeliveryService deliveryService;
    private final OrderRefundService orderRefundService;
    private final OrderItemMapper orderItemMapper;
    private final WxConfig wxConfig;
    private final PayInfoService payInfoService;
    private final DeliveryPrintManager deliveryPrintManager;
    private final ShopDetailService shopDetailService;
    private static final Logger logger = LoggerFactory.getLogger(DeliveryOrderServiceImpl.class);


    /**
     * 生成物流信息及保存物流与订单关联
     * @param deliveryOrderParam 物流信息
     * @param shopId 店铺id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public DeliveryOrder saveDeliveriesInfo(DeliveryOrderItemParam deliveryOrderParam, Long shopId) {
        List<OrderItem> selectOrderItems = deliveryOrderParam.getSelectOrderItems();
        for (OrderItem selectOrderItem : selectOrderItems) {
            if (Objects.equals(selectOrderItem.getDvyType(), DvyType.DELIVERY.value())) {
                selectOrderItem.setDvyType(DvyType.DELIVERY.value());
            } else {
                selectOrderItem.setDvyType(deliveryOrderParam.getDeliveryType());
            }
        }
        String orderNumber = deliveryOrderParam.getOrderNumber();
        Order order = orderService.getOrderAndOrderItemByOrderNumber(orderNumber);
        if(!Objects.equals(order.getShopId(),shopId)){
            // 订单不存在
            throw new YamiShopBindException("yami.order.no.exist");
        }
        deliveryOrderParam.setReceiverMobile(order.getReceiverMobile());
        deliveryOrderParam.setReceiverName(order.getReceiverName());
        deliveryOrderParam.setAddrOrderId(order.getAddrOrderId());
        boolean isSend = Objects.equals(deliveryOrderParam.getDeliveryType(),DvyType.DELIVERY.value()) ||
                Objects.equals(deliveryOrderParam.getDeliveryType(), DvyType.ONLINE.value()) ||
                Objects.equals(deliveryOrderParam.getDeliveryType(),DvyType.NOT_DELIVERY.value()) ||
                Objects.equals(deliveryOrderParam.getDeliveryType(),DvyType.SAME_CITY.value());
        DeliveryOrder deliveryOrder = checkIsSend(deliveryOrderParam, selectOrderItems, order, isSend);
        orderItemMapper.updateByDeliveries(selectOrderItems);
        //判断是否发货完成
        boolean isDelivery = checkDeliveryComplete(orderNumber, order);
        // 判断发货商品名称
        if(selectOrderItems.size() != order.getOrderItems().size()){
            Set<String> names = selectOrderItems.stream().map(OrderItem::getProdName).collect(Collectors.toSet());
            order.setProdName(names.toString());
        }
        if (Objects.equals(deliveryOrderParam.getDeliveryType(), DvyType.ONLINE.value())) {
            // 线上发货处理
            String deliveryNo = deliveryPrintManager.deliveryPrint(deliveryOrderParam);
            // 更新单号
            DeliveryOrder updateDeliveryOrder = new DeliveryOrder();
            updateDeliveryOrder.setOrderDeliveryId(deliveryOrder.getOrderDeliveryId());
            updateDeliveryOrder.setDvyFlowId(deliveryNo);
            deliveryOrderMapper.updateById(updateDeliveryOrder);
            deliveryOrderParam.setDvyFlowId(deliveryNo);
        }
        // 判断处理小程序发货
        checkWechatPayDelivery(order, deliveryOrderParam, deliveryOrder, isDelivery);
        //修改为发货状态
        isDelivery(deliveryOrderParam, isDelivery, orderNumber, order);

        return deliveryOrder;
    }


    private void isDelivery(DeliveryOrderItemParam deliveryOrderParam, boolean isDelivery, String orderNumber, Order order) {
        Date date = new Date();
        order.setUpdateTime(date);
        order.setDvyTime(date);
        //判断是无需物流还是快递发货
        order.setDvyType(deliveryOrderParam.getDeliveryType());
        // 如果是无需快递，则判断该订单是否包含有物流的项，若有物流则配送类型为快递配送，没有物流则不变
        if (Objects.equals(order.getDvyType(), DvyType.NOT_DELIVERY.value())) {
            List<DeliveryOrder> deliveryOrders = list(new LambdaQueryWrapper<DeliveryOrder>().eq(DeliveryOrder::getOrderNumber, orderNumber)
                    .eq(DeliveryOrder::getDeliveryType,DvyType.DELIVERY.value()));
            if (!CollectionUtils.isEmpty(deliveryOrders)){
                order.setDvyType(1);
            }
        }
        if(isDelivery) {
            order.setStatus(OrderStatus.CONSIGNMENT.value());
            orderService.updateById(order);
        }
        String dvyName = "";
        if(Objects.equals(order.getDvyType(),DvyType.SAME_CITY.value())){
            dvyName = "店铺同城配送";
            order.setDvyFlowId("同城配送");
        }
        // 消息推送-发货提醒
        if(Objects.equals(order.getDvyType(), DvyType.DELIVERY.value())){
            Delivery delivery = deliveryService.getById(deliveryOrderParam.getDvyId());
            order.setDvyFlowId(deliveryOrderParam.getDvyFlowId());
            dvyName = "";
            if(Objects.nonNull(delivery) && delivery.getDvyName() != null){
                dvyName = delivery.getDvyName();
            }
        }
        if (Objects.equals(order.getDvyType(), DvyType.ONLINE.value())) {
            DeliveryCompanyType deliveryCompanyType = DeliveryCompanyType.instance(deliveryOrderParam.getDeliveryCompanyType());
            if (Objects.isNull(deliveryCompanyType)) {
                throw new YamiShopBindException("网点关联快递公司配置为空");
            }
            order.setDvyFlowId(deliveryOrderParam.getDvyFlowId());
            order.setDvyId(Long.valueOf(deliveryOrderParam.getDeliveryCompanyType()));
            dvyName = deliveryCompanyType.getName();
        }
        if (Objects.equals(order.getDvyType(), DvyType.NOT_DELIVERY.value()) ||
                Objects.equals(deliveryOrderParam.getDeliveryType(), DvyType.NOT_DELIVERY.value())){
            dvyName = "无需快递";
            order.setDvyFlowId("无需快递");
        }
        notifyTemplateService.sendNotifyOfDelivery(order,dvyName, SendType.DELIVERY);
    }

    private DeliveryOrder checkIsSend(DeliveryOrderItemParam deliveryOrderParam, List<OrderItem> selectOrderItems, Order order, boolean isSend) {
        DeliveryOrder deliveryOrder = new DeliveryOrder();
        deliveryOrder.setProductNums(0);
        if (isSend){
            //校验订单状态，发货数量及获取发货的总数
            int prodNumSum = checkDelivery(order, selectOrderItems);
            deliveryOrder.setOrderNumber(deliveryOrderParam.getOrderNumber());
            if (Objects.equals(deliveryOrderParam.getDeliveryType(),DvyType.DELIVERY.value())){
                deliveryOrder.setDvyId(deliveryOrderParam.getDvyId());
                deliveryOrder.setDvyFlowId(deliveryOrderParam.getDvyFlowId());
            } else if (Objects.equals(deliveryOrderParam.getDeliveryType(),DvyType.ONLINE.value())){
                // 线上发货DeliveryCompanyId为DeliveryCompanyType中的type
                DeliveryCompanyType deliveryCompanyType = DeliveryCompanyType.instance(deliveryOrderParam.getDeliveryCompanyType());
                if (Objects.isNull(deliveryCompanyType)) {
                    throw new YamiShopBindException("yami.delivery.info.is.null");
                }
                deliveryOrder.setDvyId(Long.valueOf(deliveryCompanyType.getType()));
            }
            deliveryOrder.setCreateTime(new Date());
            deliveryOrder.setUpdateTime(new Date());
            deliveryOrder.setStatus(1);
            deliveryOrder.setReceiverMobile(order.getReceiverMobile());
            deliveryOrder.setProductNums(prodNumSum);
            deliveryOrder.setDeliveryType(deliveryOrderParam.getDeliveryType());
            //保存订单物流信息
            save(deliveryOrder);
            //保存需要添加的关联信息
            List<DeliveryOrderItem> addDeliveries = new ArrayList<>();
            for (OrderItem selectOrderItem : selectOrderItems) {
                DeliveryOrderItem deliveryOrderItem = new DeliveryOrderItem();
                deliveryOrderItem.setOrderItemId(selectOrderItem.getOrderItemId());
                deliveryOrderItem.setProdCount(selectOrderItem.getChangeNum());
                deliveryOrderItem.setOrderDeliveryId(deliveryOrder.getOrderDeliveryId());
                addDeliveries.add(deliveryOrderItem);
            }
            if(CollectionUtils.isNotEmpty(addDeliveries)){
                deliveryOrderItemService.saveBatch(addDeliveries);
            }
        }
        return deliveryOrder;
    }


    /**
     * 修改物流信息
     * @param deliveryOrders 物流修改的信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateOrderDeliveries(List<DeliveryOrder> deliveryOrders) {
        updateWechatPayDelivery(deliveryOrders);
        deliveryOrders.forEach(deliveryOrder-> deliveryOrder.setUpdateTime(new Date()));
        updateBatchById(deliveryOrders);
    }

    @Override
    public List<DeliveryOrder> getAndDeliveryItemInfo(String orderNumber) {
        List<DeliveryOrder> deliveryOrders = deliveryOrderMapper.getAndDeliveryItemInfo(orderNumber, null);
        if (CollUtil.isEmpty(deliveryOrders)) {
            return new ArrayList<>();
        }
        // 查询物流详情信息
        // 物流公司名称、官网、订单号、物流详情信息
        DeliveryOrder deliveryOrder = deliveryOrders.get(0);
        if (Objects.nonNull(deliveryOrder.getDvyId())){
            // 查询交易单
            DeliveryDto deliveryDto = getDelivery(deliveryOrder);
            deliveryOrder.setDeliveryDto(deliveryDto);
            if(Objects.nonNull(deliveryOrder.getDeliveryDto()) && CollectionUtils.isNotEmpty(deliveryOrder.getDeliveryDto().getTraces())){
                // 按照时间正序排列返回给前端
                List<DeliveryInfoDto> deliveryInfoList = deliveryOrder.getDeliveryDto().getTraces().stream().sorted(Comparator.comparing(DeliveryInfoDto::getAcceptTime)).toList();
                deliveryOrder.getDeliveryDto().setTraces(deliveryInfoList);
            }
        }
        for (DeliveryOrder order : deliveryOrders) {
            Map<Long, List<OrderItemParam>> itemMap = order.getOrderItems().stream().collect(Collectors.groupingBy(OrderItemParam::getOrderItemId));
            List<OrderItemParam> orderItemParams = new ArrayList<>();
            for (Long orderItemId : itemMap.keySet()) {
                int sum = itemMap.get(orderItemId).stream().mapToInt(OrderItemParam::getProdCount).sum();
                OrderItemParam orderItemParam = itemMap.get(orderItemId).get(0);
                orderItemParam.setProdCount(sum);
                orderItemParams.add(orderItemParam);
            }
            // 根据订单项id排序
            orderItemParams = orderItemParams.stream().sorted(Comparator.comparing(OrderItemParam::getOrderItemId)).collect(Collectors.toList());
            order.setOrderItems(orderItemParams);
            for (OrderItemParam orderItem : deliveryOrder.getOrderItems()) {
                orderItem.setOrderType(deliveryOrder.getOrderType());
                if (Objects.equals(orderItem.getActivityType(),OrderActivityType.GIVEAWAY.value())){
                    orderItem.setType(1);
                }
            }
        }
        return deliveryOrders;
    }

    @Override
    public List<DeliveryOrder> listDetailDelivery(String orderNumber) {
        return deliveryOrderMapper.listDetailDelivery(orderNumber);
    }

    @Override
    public DeliveryOrder deliveryOrderItemInfo(Long orderDeliveryId) {
        List<DeliveryOrder> deliveryOrders = deliveryOrderMapper.getAndDeliveryItemInfo(null, orderDeliveryId);
        for (DeliveryOrder deliveryOrder : deliveryOrders) {
            for (OrderItemParam orderItem : deliveryOrder.getOrderItems()) {
                orderItem.setOrderType(deliveryOrder.getOrderType());
                if (Objects.equals(orderItem.getActivityType(),OrderActivityType.GIVEAWAY.value())){
                    orderItem.setType(1);
                }

                if (!Objects.equals(orderItem.getPreSellStatus(), StatusEnum.ENABLE.value())){
                    orderItem.setPreSaleTime(null);
                }
            }
        }
        if (CollUtil.isEmpty(deliveryOrders)) {
            return new DeliveryOrder();
        }
        DeliveryOrder deliveryOrder = deliveryOrders.get(0);
        if (Objects.nonNull(deliveryOrder) && Objects.nonNull(deliveryOrder.getDvyId())){
            // 查询交易单
            DeliveryDto deliveryDto = getDelivery(deliveryOrder);
            deliveryOrder.setDeliveryDto(deliveryDto);
            if(Objects.nonNull(deliveryOrder.getDeliveryDto()) && CollectionUtils.isNotEmpty(deliveryOrder.getDeliveryDto().getTraces())){
                Collections.reverse(deliveryOrder.getDeliveryDto().getTraces());
            }
        }
        // 处理下相同的sku信息集合
        Map<Long, List<OrderItemParam>> itemMap = deliveryOrder.getOrderItems().stream().collect(Collectors.groupingBy(OrderItemParam::getSkuId));
        List<OrderItemParam> orderItemParams = new ArrayList<>();
        for (Long skuId : itemMap.keySet()) {
            int sum = itemMap.get(skuId).stream().mapToInt(OrderItemParam::getProdCount).sum();
            OrderItemParam orderItemParam = itemMap.get(skuId).get(0);
            orderItemParam.setProdCount(sum);
            orderItemParams.add(orderItemParam);
        }
        deliveryOrder.setOrderItems(orderItemParams);
        return deliveryOrder;
    }

    private DeliveryDto getDelivery(DeliveryOrder deliveryOrder){
        DeliveryDto deliveryDto;
        try {
            Delivery delivery = new Delivery();
            if (Objects.equals(deliveryOrder.getDeliveryType(), DeliveryType.EXPRESS.getValue())) {
                delivery = deliveryService.getById(deliveryOrder.getDvyId());
            } else if (Objects.equals(deliveryOrder.getDeliveryType(), DeliveryType.ONLINE.getValue())){
                delivery = DeliveryCompanyType.getByDeliveryCompanyType(deliveryOrder.getDvyId());
            }
            // 解析的物流详情明细
            deliveryDto = deliveryService.query(delivery, deliveryOrder.getDvyFlowId(), deliveryOrder.getReceiverMobile());
            deliveryDto.setCompanyHomeUrl(delivery.getCompanyHomeUrl());
            deliveryDto.setCompanyName(delivery.getDvyName());
            deliveryDto.setDvyFlowId(deliveryOrder.getDvyFlowId());
        } catch (Exception e) {
            log.error("物流查询错误：", e);
            // 查询出错
            throw new YamiShopBindException("yami.query.error");
        }
        return deliveryDto;
    }

    /**
     * 校验可发货数量并返回总数
     * @param order 订单信息
     * @param selectOrderItems 选择发货的订单项
     */
    private int checkDelivery(Order order, List<OrderItem> selectOrderItems) {
        if (!Objects.equals(order.getStatus(), OrderStatus.PADYED.value()) && Objects.equals(order.getDvyType(), DvyType.STATION.value())) {
            // 订单不处于待入库状态，无法进行入库
            throw new YamiShopBindException("yami.order.status.no.right");
        } else if (!Objects.equals(order.getStatus(), OrderStatus.PADYED.value())) {
            // 订单不处于待发货状态，无法进行发货
            throw new YamiShopBindException("yami.order.delivery.no.right");
        }
        List<OrderRefund> orderRefunds = orderRefundService.getProcessingOrderRefundByOrderId(order.getOrderId());
        // 移除退款成功的退款记录
        orderRefunds.removeIf(orderRefund -> orderRefund.getReturnMoneySts() == 5);
        if (CollectionUtil.isNotEmpty(orderRefunds)) {
            // 该订单有退款信息正在处理当中，请处理完毕之后再进行发货的操作!
            throw new YamiShopBindException("yami.order.delivery.refund.error");
        }
        Map<Long, OrderItem> itemMap = order.getOrderItems().stream().collect(Collectors.toMap(OrderItem::getOrderItemId, orderItem -> orderItem));
        //获取发货总数
        int prodNumSum = 0;
        for (OrderItem selectOrderItem : selectOrderItems) {
            prodNumSum += selectOrderItem.getChangeNum();
            if(!itemMap.containsKey(selectOrderItem.getOrderItemId())){
                // 订单不存在
                throw new YamiShopBindException("yami.order.no.exist");
            }
            OrderItem orderItemDb = itemMap.get(selectOrderItem.getOrderItemId());
            // 这里把数据库查询到的数量放进去，以免前端传了错误的数量
            selectOrderItem.setProdCount(Objects.equals(orderItemDb.getStatus(),-1) ? orderItemDb.getProdCount() : orderItemDb.getStatus());
            if(!Objects.equals(orderItemDb.getStatus(),-1) && orderItemDb.getStatus() < selectOrderItem.getChangeNum()){
                // 订单发货数量不足，请刷新后再试
                throw new YamiShopBindException("yami.order.delivery.num.check");
            }
        }
        return prodNumSum;
    }

    /**
     * 小程序发货处理,录入发货信息
     * @param order
     * @param deliveryOrderParam
     * @param deliveryOrder
     * @param isDelivery
     */
    private void checkWechatPayDelivery(Order order, DeliveryOrderItemParam deliveryOrderParam, DeliveryOrder deliveryOrder, Boolean isDelivery) {
        // 查询小程序是否已开通发货信息管理服务
        Boolean managed = wxConfig.getTradeManaged();
        if (!managed) {
            return;
        }
        PayInfo payInfo = payInfoService.getOne(new LambdaQueryWrapper<PayInfo>()
                .eq(PayInfo::getPayStatus, PayStatus.PAYED.value())
                .eq(PayInfo::getPayEntry, PayEntry.ORDER.value())
                .like(PayInfo::getOrderNumbers, order.getOrderNumber())
                .orderByDesc(PayInfo::getCreateTime)
                .last("limit 1"));
        // 判断是否是小程序购买
        if (Objects.nonNull(payInfo) && Objects.equals(payInfo.getPayType(), PayType.WECHATPAY.value()) && Objects.equals(payInfo.getSystemType(), FlowSystemTypeEnum.APPLETS.value())) {
            boolean numFlag = deliveryOrder.getProductNums().equals(order.getProductNums());
            if (isDelivery && numFlag) {
                // 统一发货
                upload(deliveryOrderParam, order, payInfo);
            }
            if (isDelivery && !numFlag){
                // 多包裹发货
                combinedUpload(deliveryOrderParam, order, payInfo);
            }
        }
    }

    /**
     * 修改小程序发货，只能修改一次
     * @param deliveryOrders
     */
    private void updateWechatPayDelivery(List<DeliveryOrder> deliveryOrders) {
        // 查询小程序是否已开通发货信息管理服务
        Boolean managed = wxConfig.getTradeManaged();
        if (!managed) {
            return;
        }
        PayInfo payInfo = payInfoService.getOne(new LambdaQueryWrapper<PayInfo>()
                .eq(PayInfo::getPayStatus, PayStatus.PAYED.value())
                .eq(PayInfo::getPayEntry, PayEntry.ORDER.value())
                .like(PayInfo::getOrderNumbers, deliveryOrders.get(0).getOrderNumber())
                .orderByDesc(PayInfo::getCreateTime)
                .last("limit 1"));
        // 判断是否小程序购买
        if (Objects.nonNull(payInfo) && Objects.equals(payInfo.getPayType(), PayType.WECHATPAY.value()) && Objects.equals(payInfo.getSystemType(), FlowSystemTypeEnum.APPLETS.value())) {
            WxMaOrderCombinedShippingInfoUploadRequest request = new WxMaOrderCombinedShippingInfoUploadRequest();
            OrderKeyBean orderKey = new OrderKeyBean();
            orderKey.setOrderNumberType(2);
            orderKey.setTransactionId(payInfo.getBizPayNo());
            request.setOrderKey(orderKey);
            WxMaOrderCombinedShippingInfoUploadRequest.SubOrderBean subOrderBean = new WxMaOrderCombinedShippingInfoUploadRequest.SubOrderBean();
            subOrderBean.setOrderKey(orderKey);
            subOrderBean.setDeliveryMode(2);
            subOrderBean.setLogisticsType(deliveryOrders.get(0).getDeliveryType());
            subOrderBean.setIsAllDelivered(true);
            List<ShippingListBean> shippingListBeanList = new ArrayList<>();
            for (DeliveryOrder deliveryOrder : deliveryOrders) {
                if (deliveryOrder.getCreateTime().getTime() != deliveryOrder.getUpdateTime().getTime()) {
                    // 已经修改过一次了，不能再次修改小程序发货信息
                    break;
                }
                ShippingListBean shippingListBean = new ShippingListBean();
                shippingListBean.setTrackingNo(deliveryOrder.getDvyFlowId());
                Delivery delivery = deliveryService.getById(deliveryOrder.getDvyId());
                shippingListBean.setExpressCompany(delivery.getDvyNo() == null ? delivery.getDvyNoHd() : delivery.getDvyNo());
                String itemDesc = "";
                for (OrderItemParam orderItem : deliveryOrder.getOrderItems()) {
                    itemDesc += orderItem.getProdName() + "*" + orderItem.getProdCount() + "    ";
                }
                shippingListBean.setItemDesc(itemDesc);
                String key = "顺丰";
                if (delivery.getDvyName().contains(key)) {
                    ContactBean contactBean = new ContactBean();
                    contactBean.setReceiverContact(deliveryOrder.getReceiverMobile().replaceAll("(\\d{3})\\d{4}(\\d{4})","$1****$2"));
                    shippingListBean.setContact(contactBean);
                }
                shippingListBeanList.add(shippingListBean);
            }
            if(shippingListBeanList.isEmpty()){
                return;
            }
            subOrderBean.setShippingList(shippingListBeanList);
            request.setSubOrders(Collections.singletonList(subOrderBean));
            DateFormat dft = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
            request.setUploadTime(dft.format(new Date()));
            PayerBean payerBean = new PayerBean();
            payerBean.setOpenid(payInfo.getBizUserId());
            request.setPayer(payerBean);
            try {
                WxMaService wxMaService = wxConfig.getWxMaService();
                WxMaOrderShippingService wxMaOrderShippingService = new WxMaOrderShippingServiceImpl(wxMaService);
                wxMaOrderShippingService.upload(request);
            } catch (WxErrorException wxErrorException) {
                wxErrorException.printStackTrace();
                throw new YamiShopBindException(wxErrorException.getError().getErrorMsg());
            }
        }
    }

    /**
     * 发货信息录入接口,统一发货（一次性全部发货）
     * @param deliveryOrderParam
     * @param order
     * @param payInfo
     */
    private void upload(DeliveryOrderItemParam deliveryOrderParam, Order order, PayInfo payInfo) {
        // 统一发货
        WxMaOrderShippingInfoUploadRequest request = new WxMaOrderShippingInfoUploadRequest();
        OrderKeyBean orderKey = new OrderKeyBean();
        orderKey.setOrderNumberType(2);
        orderKey.setTransactionId(payInfo.getBizPayNo());
        request.setOrderKey(orderKey);
        request.setDeliveryMode(1);
        request.setLogisticsType(deliveryOrderParam.getDeliveryType());
        request.setShippingList(Collections.singletonList(createShippingBean(deliveryOrderParam, order)));
        DateFormat dft = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
        request.setUploadTime(dft.format(new Date()));
        PayerBean payerBean = new PayerBean();
        payerBean.setOpenid(payInfo.getBizUserId());
        request.setPayer(payerBean);
        try {
            WxMaService wxMaService = wxConfig.getWxMaService();
            WxMaOrderShippingService wxMaOrderShippingService = new WxMaOrderShippingServiceImpl(wxMaService);
            wxMaOrderShippingService.upload(request);
        } catch (WxErrorException wxErrorException) {
            wxErrorException.printStackTrace();
            throw new YamiShopBindException(wxErrorException.getError().getErrorMsg());
        }
    }

    /**
     * 发货信息合单录入接口,多包裹发货（多次发货）
     * @param deliveryOrderParam
     * @param order
     * @param payInfo
     */
    private void combinedUpload(DeliveryOrderItemParam deliveryOrderParam, Order order, PayInfo payInfo) {
        // 分批发货
        WxMaOrderCombinedShippingInfoUploadRequest request = new WxMaOrderCombinedShippingInfoUploadRequest();
        OrderKeyBean orderKey = new OrderKeyBean();
        orderKey.setOrderNumberType(2);
        orderKey.setTransactionId(payInfo.getBizPayNo());
        request.setOrderKey(orderKey);
        WxMaOrderCombinedShippingInfoUploadRequest.SubOrderBean subOrderBean = new WxMaOrderCombinedShippingInfoUploadRequest.SubOrderBean();
        subOrderBean.setOrderKey(orderKey);
        subOrderBean.setDeliveryMode(2);
        subOrderBean.setLogisticsType(deliveryOrderParam.getDeliveryType());
        subOrderBean.setIsAllDelivered(true);
        List<ShippingListBean> shippingListBeanList = new ArrayList<>();
        shippingListBeanList.add(createShippingBean(deliveryOrderParam, order));
        List<DeliveryOrder> deliveryOrderList = getAndDeliveryItemInfo(order.getOrderNumber());
        for (DeliveryOrder deliveryOrder : deliveryOrderList) {
            ShippingListBean shippingListBean = new ShippingListBean();
            shippingListBean.setTrackingNo(deliveryOrder.getDvyFlowId());
            Delivery delivery = deliveryService.getById(deliveryOrder.getDvyId());
            shippingListBean.setExpressCompany(delivery.getDvyNo() == null ? delivery.getDvyNoHd() : delivery.getDvyNo());
            String itemDesc = "";
            for (OrderItemParam orderItem : deliveryOrder.getOrderItems()) {
                itemDesc += orderItem.getProdName() + "*" + orderItem.getProdCount() + "    ";
            }
            shippingListBean.setItemDesc(itemDesc);
            String key = "顺丰";
            if (delivery.getDvyName().contains(key)) {
                ContactBean contactBean = new ContactBean();
                contactBean.setReceiverContact(order.getReceiverMobile().replaceAll("(\\d{3})\\d{4}(\\d{4})","$1****$2"));
                shippingListBean.setContact(contactBean);
            }
            shippingListBeanList.add(shippingListBean);
        }
        subOrderBean.setShippingList(shippingListBeanList);
        request.setSubOrders(Collections.singletonList(subOrderBean));
        DateFormat dft = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
        request.setUploadTime(dft.format(new Date()));
        PayerBean payerBean = new PayerBean();
        payerBean.setOpenid(payInfo.getBizUserId());
        request.setPayer(payerBean);
        try {
            WxMaService wxMaService = wxConfig.getWxMaService();
            WxMaOrderShippingService wxMaOrderShippingService = new WxMaOrderShippingServiceImpl(wxMaService);
            wxMaOrderShippingService.upload(request);
        } catch (WxErrorException wxErrorException) {
            wxErrorException.printStackTrace();
            throw new YamiShopBindException(wxErrorException.getError().getErrorMsg());
        }
    }

    /**
     * 创建小程序发货的包裹信息
     * @param deliveryOrderParam
     * @param order
     * @return
     */
    private ShippingListBean createShippingBean(DeliveryOrderItemParam deliveryOrderParam, Order order) {
        ShippingListBean shippingListBean = new ShippingListBean();
        shippingListBean.setTrackingNo(deliveryOrderParam.getDvyFlowId());
        shippingListBean.setExpressCompany(null);
        if (Objects.nonNull(deliveryOrderParam.getDvyId())){
            Delivery delivery = deliveryService.getById(deliveryOrderParam.getDvyId());
            shippingListBean.setExpressCompany(delivery.getDvyNo() == null ? delivery.getDvyNoHd() : delivery.getDvyNo());
            String key = "顺丰";
            if (delivery.getDvyName().contains(key)) {
                ContactBean contactBean = new ContactBean();
                contactBean.setReceiverContact(order.getReceiverMobile().replaceAll("(\\d{3})\\d{4}(\\d{4})","$1****$2"));
                shippingListBean.setContact(contactBean);
            }
        }
        String itemDesc = "";
        for (OrderItem orderItem : deliveryOrderParam.getSelectOrderItems()) {
            itemDesc += orderItem.getProdName() + "*" + orderItem.getChangeNum() + "    ";
        }
        shippingListBean.setItemDesc(itemDesc);
        return shippingListBean;
    }

    private boolean checkDeliveryComplete(String orderNumber, Order order) {
        boolean isDelivery = true;
        List<OrderItem> orderItems;
        // 处理一下组合商品的发货
        if(order.getOrderItems().stream().filter(orderItem -> Objects.equals(orderItem.getMold(), ProdMoldEnum.COMBO.value())).count() > 0){
            orderItems = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderNumber, orderNumber));
            Map<Long, List<OrderItem>> childComboItems = orderItems.stream().filter(orderItem -> Objects.equals(orderItem.getActivityType(), OrderActivityType.COMBO_PROD.value()) && !Objects.equals(orderItem.getStatus(),-1))
                    .collect(Collectors.groupingBy(OrderItem::getActivityId));
            List<OrderItem> updateOrderItems = new ArrayList<>();
            for (Long mainItemId : childComboItems.keySet()) {
                // 检查下是否所有的子组合项都发货了
                List<OrderItem> items = childComboItems.get(mainItemId);
                long unDeliveryCount = items.stream().filter(orderItem -> !Objects.equals(orderItem.getStatus(), 0)).count();
                if(unDeliveryCount == 0){
                    long count = items.stream().filter(orderItem -> Objects.equals(orderItem.getDvyType(), DvyType.DELIVERY.value())).count();
                    OrderItem orderItem = new OrderItem();
                    orderItem.setOrderItemId(mainItemId);
                    orderItem.setStatus(0);
                    // 如果有一个快递发货的方式,那就是快递发货,否则就是第一个的发货方式,因为如果是自提/同城配送/无需快递那就都是这三
                    orderItem.setDvyType(count > 0 ? DvyType.DELIVERY.value() : items.get(0).getDvyType());
                    orderItemMapper.updateById(orderItem);
                }
            }
        }
        if (Objects.isNull(order.getRefundStatus())){
            orderItems = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderNumber, orderNumber));
        }else {
            orderItems = orderItemMapper.getListByOrderNumber(orderNumber);
            List<Long> orderItemIds = orderItems.stream().map(OrderItem::getOrderItemId).toList();
            orderItems.removeIf(orderItem -> Objects.equals(orderItem.getActivityType(),OrderActivityType.GIVEAWAY.value()) && !orderItemIds.contains(orderItem.getActivityId()));
            orderItems.removeIf(orderItem -> Objects.equals(orderItem.getActivityType(),OrderActivityType.COMBO_PROD.value()));
        }
        // 有多个商品的订单，有退款记录的，并且有退款成功的单个商品，
        // 其余的商品都是发货完成的订单，改成发货状态
        // 在退款处理的时候将状态改为0即可
        for (OrderItem orderItem : orderItems) {
            if (orderItem.getStatus() != 0) {
                isDelivery = false;
                break;
            }
        }
        List<DeliveryOrder> deliveryOrders = listDetailDelivery(orderNumber);
        if (deliveryOrders.size() >= 10 && !isDelivery) {
            throw new YamiShopBindException("yami.order.deliver.size.exist");
        }
        return isDelivery;
    }
}
